<?php
/**
  * CLOUD
  *
  * This is not a freeware, use is subject to license terms
  * @author CLOUD DEV TEAM
  * 
  */
if (!defined('IN_CLOUD')) exit('Access Denied!');

abstract class Model
{
	protected $tableName;
	
	protected $tablepre;
	
	protected $db = null;
	
	protected $dbconfig = array();
	
	protected $dbType;
	
	protected function __construct()
	{
		$this->dbconfig = Common::getConfig( 'Database' );
		$this->tablepre = $this->dbconfig['pre'];
		$this->tableName = $this->tablepre . $this->tableName;
		$this->db = Db::createDb( $this->dbconfig['dbType'] );
	}
	
	/**
	 * 设置数据表
	 * @param string $table
	 */
	public function setTableName( $table )
	{
		$this->tableName = $table;
	}
	
	/**
	 * 执行sql查询
	 * @param array|string $where 		查询条件[`name`='$name']
	 * @param string $data 				需要查询的字段值[`name`,`gender`]
	 * @param string $limit 					返回结果范围[：10或10,10 默认为空]
	 * @param string $order 					排序方式	[默认按数据库默认方式排序]
	 * @param $group 					分组方式	[默认为空]
	 * @param $key          			返回数组按键名排序
	 * @return array					查询结果集数组
	 */
	final public function select( $where = '' , $data = '*' , $limit = '' , $order = '' , $group = '' , $key = '' ) 
	{
		if ( is_array( $where ) ) $where = $this->sqls( $where );
		return $this->db->select( $data , $this->tableName , $where , $limit , $order , $group , $key );
	}

	/**
	 * 获取单条记录查询
	 * @param array|string $where 		查询条件
	 * @param string $data 		需要查询的字段值[`name`,`gender`,`birthday`]
	 * @param string $order 		排序方式	[默认按数据库默认方式排序]
	 * @param $group 		分组方式	[默认为空]
	 * @return array/null	数据查询结果集,如果不存在，则返回空
	 */
	final public function getOne( $where = '' , $data = '*' , $order = '' , $group = '' )
	{
		if ( is_array( $where ) ) $where = $this->sqls( $where );
		return $this->db->getOne( $data , $this->tableName , $where , $order , $group );
	}
	
	/**
	 * 根据SQL直接获取单条记录
	 * @param string $sql
	 */
	final public function getOneBySql ( $sql )
	{
		return $this->db->getOneBySql( $sql );
	}
	
	/**
	 * 直接执行sql查询
	 * @param string $sql							查询sql语句
	 * @return	boolean/query resource		如果为查询语句，返回资源句柄，否则返回true/false
	 */
	final public function query( $sql ) 
	{
		return $this->db->query( $sql );
	}
	
	/**
	 * 执行添加记录操作
	 * @param array $data 			要增加的数据，参数为数组。数组key为字段值，数组值为数据取值
	 * @param bool $returnInsertId 	是否返回新建ID号
	 * @param bool $isReplace 		是否采用 replace into的方式添加数据
	 * @return boolean
	 */
	final public function insert( $data , $returnInsertId = false , $isReplace = false ) 
	{
		return $this->db->insert( $data , $this->tableName , $returnInsertId, $isReplace );
	}
	
	/**
	 * 获取最后一次添加记录的主键号
	 * @return int 
	 */
	final public function insertId() 
	{
		return $this->db->insertId();
	}
	
	/**
	 * 执行更新记录操作
	 * @param array $data 		要更新的数据内容，参数可以为数组也可以为字符串，建议数组。
	 * 						为数组时数组key为字段值，数组值为数据取值
	 * 						为字符串时[例：`name`='phpcms',`hits`=`hits`+1]。
	 *						为数组时[例: array('name'=>'phpcms','password'=>'123456')]
	 *						数组的另一种使用array('name'=>'+=1', 'base'=>'-=1');程序会自动解析为`name` = `name` + 1, `base` = `base` - 1
	 * @param array $where 		更新数据时的条件,可为数组或字符串
	 * @return boolean
	 */
	final public function update( $data , $where = '' ) 
	{
		if (is_array($where)) $where = $this->sqls( $where );
		return $this->db->update( $data , $this->tableName , $where );
	}
	
	/**
	 * 执行删除记录操作
	 * @param array|string $where 		删除数据条件,不充许为空。
	 * @return boolean
	 */
	final public function delete( $where ) 
	{
		if ( is_array( $where ) ) $where = $this->sqls( $where );
		return $this->db->delete( $this->tableName , $where );
	}
	
	/**
	 * 计算记录数
	 * @param string/array $where 查询条件
	 */
	final public function count( $where = '' ) 
	{
		$r = $this->getOne( $where , "COUNT(*) AS num" );
		return $r['num'];
	}
	
	/**
	 * 将数组转换为SQL语句
	 * @param array $where 要生成的数组
	 * @param string $font 连接串。
	 */
	final public function sqls( $where , $font = ' AND ' ) 
	{
		if ( is_array( $where ) ) 
		{
			$sql = '';
			foreach ( $where as $key => $val ) 
			{
				if ( !in_array( substr( $val ,  0 , 2 ) , array( '<' , '<=' , '>' , '>=' , '!=' ) ) )
				{
					$sql .= $sql ? " $font `$key` = '$val' " : " `$key` = '$val'";
				}
				else
				{
					$sql .= $sql ? " $font `$key` " . substr( $val ,  0 , 2 ) . " '$val' " : " `$key` " . substr( $val ,  0 , 2 ) . " '$val'";
				}
			}
			return $sql;
		} 
		else 
		{
			return $where;
		}
	}
	
	/**
	 * 获取最后数据库操作影响到的条数
	 * @return int
	 */
	final public function affectedRows() 
	{
		return $this->db->affectedRows();
	}
	
	/**
	 * 获取数据表主键
	 * @return array
	 */
	final public function getPrimary() 
	{
		return $this->db->getPrimary( $this->tableName );
	}
	
	/**
	 * 获取表字段
	 * @param string $tableName    表名
	 * @return array
	 */
	final public function getFields( $tableName = '' ) 
	{
		if ( empty( $tableName ) ) 
		{
			$tableName = $this->tableName;
		} 
		else 
		{
			$tableName = $this->tablepre . $tableName;
		}
		return $this->db->getFields( $tableName );
	}
	
	/**
	 * 检查表是否存在
	 * @param string $table 表名
	 * @return boolean
	 */
	final public function tableExists( $table )
	{
		return $this->db->table_exists( $this->tablepre . $table );
	}
	
	/**
	 * 检查字段是否存在
	 * @param string $field 字段名
	 * @return boolean
	 */
	public function fieldExists( $field ) 
	{
		$fields = $this->db->getFields( $this->tableName );
		return array_key_exists( $field , $fields );
	}
	
	/**
	 * 列出数据表
	 */
	final public function listTables() 
	{
		return $this->db->list_tables();
	}
	/**
	 * 返回数据结果集
	 * @param $query （mysql_query返回值）
	 * @return array
	 */
	final public function fetchArray() 
	{
		$data = array();
		while( $r = $this->db->fetchNext() ) 
		{
			$data[] = $r;		
		}
		return $data;
	}
	
	/**
	 * 返回数据库版本号
	 */
	final public function version() 
	{
		return $this->db->version();
	}
	
	/**
	 * 生成sql语句，如果传入$inCloumn且$data是数组， 生成格式为 IN('a', 'b', 'c')
	 * @param $data 条件数组或者字符串
	 * @param $front 连接符
	 * @param $inColumn 字段名称
	 * @return string
	 */
	public static function convertToSql( $data , $front = ' AND ' , $inColumn = false ) 
	{
		if( $inColumn && is_array( $data ) ) 
		{
			$ids = '\'' . implode( '\',\'' , $data ) . '\'';
			$sql = "$inColumn IN ($ids)";
			return $sql;
		} 
		else 
		{
			if ( $front == '' ) 
			{
				$front = ' AND ';
			}
			if( is_array( $data ) && count( $data ) > 0 ) 
			{
				$sql = '';
				foreach ( $data as $key => $val ) 
				{
					$sql .= $sql ? " $front `$key` = '$val' " : " `$key` = '$val' ";	
				}
				return $sql;
			} 
			else 
			{
				return $data;
			}
		}
	}
	
}